package cfca.seal.util;

import cfca.sadk.lib.crypto.JCrypto;
import cfca.sadk.lib.crypto.Session;
import cfca.sadk.util.Base64;
import cfca.sadk.util.KeyUtil;
import cfca.sadk.util.Signature;
import cfca.seal.system.Env;
import cfca.twoDimensionCode.validator.TwoDimensionCodeValidator;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.security.PrivateKey;
import java.util.Hashtable;
import javax.imageio.ImageIO;

public class QRUtil
{
  public static final String PNG = "png";

  public static String makeQR(String QRData)
    throws Exception
  {
    BarcodeFormat format = BarcodeFormat.QR_CODE;
    Hashtable hints = new Hashtable();
    hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
    hints.put(EncodeHintType.MARGIN, Integer.valueOf(0));

    QRData = new String(QRData.getBytes("UTF-8"), "ISO-8859-1");
    QRCodeWriter writer = new QRCodeWriter();
    BitMatrix bitMatrix = writer.encode(QRData, format, 200, 200, hints);
    BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(image, "png", baos);
    byte[] result = baos.toByteArray();
    return Base64.toBase64String(result);
  }

  public static String certQR(String content) throws Exception
  {
    try {
      JCrypto.getInstance().initialize("JSOFT_LIB", null);
      Session session = JCrypto.getInstance().openSession("JSOFT_LIB");

      byte[] signData = "".getBytes();
      PrivateKey priKey;
      if ("SM3-SM2".equals(Env.signAlg)) {
        String sm2Path = Env.configDir + File.separator + "QRCodeCert" + File.separator + "doublecer1_Encrypt.SM2";
        priKey = KeyUtil.getPrivateKeyFromSM2(sm2Path, "111111");
        signData = new Signature().p1SignMessage("sm3WithSM2Encryption", content.getBytes("UTF-8"), priKey, session);
      } else {
        String rsaPath = Env.configDir + File.separator + "QRCodeCert" + File.separator + "RSA.pfx";
        priKey = KeyUtil.getPrivateKeyFromPFX(rsaPath, "cfca1234");
        signData = new Signature().p1SignMessage("sha256WithRSAEncryption", content.getBytes("UTF-8"), priKey, session);
      }

      byte[] srcBytes = (content + "@#@").getBytes("UTF-8");
      byte[] buffer = new byte[signData.length + srcBytes.length];
      System.arraycopy(srcBytes, 0, buffer, 0, srcBytes.length);
      System.arraycopy(signData, 0, buffer, srcBytes.length, signData.length);

      String contents = new String(Base64.encode(buffer));

      TwoDimensionCodeValidator.validateImageSrcData(content);
      TwoDimensionCodeValidator.validatePrivateKey(priKey);
      TwoDimensionCodeValidator.validateSignAlg(Env.signAlg);
      TwoDimensionCodeValidator.validateTDCData(contents);
      TwoDimensionCodeValidator.validateImageSize(200, 200);

      Hashtable hints = new Hashtable();

      hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");

      hints.put(EncodeHintType.MARGIN, Integer.valueOf(1));

      BitMatrix matrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, 200, 200, hints);
      BufferedImage image = MatrixToImageWriter.toBufferedImage(matrix);

      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ImageIO.write(image, "png", baos);
      byte[] result = baos.toByteArray();
      return Base64.toBase64String(result);
    } catch (Exception e) {
      throw e;
    }
  }
}